﻿using System;
using System.ComponentModel;

namespace JobBatDeal.Common
{
    /// <summary>
    ///  数据类型工具
    /// </summary>
    public static class ConvertKit
    {
        #region Convert 类型转换
        /// <summary>
        ///  类型转换
        /// </summary>
        /// <typeparam name="TValue">目标类型</typeparam>
        /// <param name="value">被转换的值</param>
        /// <param name="defaultValue">转换失败时返回默认值</param>
        /// <returns></returns>
        public static TValue Convert<TValue>(object value, TValue defaultValue)
        {
            TValue newValue;
            try
            {
                if (value != null && value is TValue)
                {
                    newValue = (TValue)value;
                }
                else
                {
                    value = System.Convert.ChangeType(value, typeof(TValue));
                    newValue = (TValue)value;
                    if (newValue.Equals(null))
                    {
                        return defaultValue;
                    }
                }
            }
            catch (Exception)
            {
                newValue = defaultValue;
            }
            return newValue;
        }

        #endregion

        #region Convert Convert 类型转换(Nullable)
        /// <summary>
        ///  类型转换(Nullable)
        /// </summary>
        /// <typeparam name="TValue">目标类型</typeparam>
        /// <param name="value">被转换的值</param>
        /// <param name="defaultValue">转换失败时返回默认值</param>
        /// <returns></returns>
        public static TValue? Convert<TValue>(object value, TValue? defaultValue) where TValue : struct
        {
            TValue? newValue;
            try
            {
                if (value != null && value is TValue)
                {
                    newValue = (TValue)value;
                }
                else
                {
                    value = System.Convert.ChangeType(value, typeof(TValue));
                    newValue = (TValue)value;
                }
            }
            catch (Exception)
            {
                newValue = defaultValue;
            }
            return newValue;
        }
        #endregion

        #region LongToInt32 将long型数值转换为Int32类型
        /// <summary>
        /// 将long型数值转换为Int32类型
        /// </summary>
        /// <param name="target"></param>
        /// <returns></returns>
        //public static int SafeInt32(object target)
        //{
        //    if (target == null)
        //    {
        //        return 0;
        //    }
        //    string numString = target.ToString();
        //    if (ValidateKit.IsNumeric(numString))
        //    {
        //        if (numString.Length > 9)
        //        {
        //            if (numString.StartsWith("-"))
        //            {
        //                return int.MinValue;
        //            }
        //            return int.MaxValue;
        //        }
        //        return Int32.Parse(numString);
        //    }
        //    return 0;
        //}
        #endregion

        #region ChangeType 装箱类型转换 兼容Nullable类型
        /// <summary>
        ///  装箱类型转换 兼容Nullable类型
        /// </summary>
        /// <param name="value"></param>
        /// <param name="conversionType"></param>
        /// <returns></returns>
        public static object ChangeType(object value, Type conversionType)
        {
            if (conversionType == null)
            {
                throw new ArgumentNullException("conversionType");
            }
            if (conversionType.IsGenericType &&
                conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
            {
                if (value == null)
                {
                    return null;
                }
                var nullableConverter = new NullableConverter(conversionType);
                conversionType = nullableConverter.UnderlyingType;
            }
            return System.Convert.ChangeType(value, conversionType);
        }
        #endregion

        #region ToInt16
        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static short ToInt16(object value, short defaultValue)
        {
            if (value != null)
            {
                short temp;
                if (short.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static short ToInt16(object value)
        {
            return ToInt16(value, 0);
        }
        #endregion

        #region ToInt32
        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static int ToInt32(object value, int defaultValue)
        {
            if (value != null)
            {
                int temp;
                if (int.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static int? ToInt32(object value, int? defaultValue)
        {
            if (value != null)
            {
                int temp;
                if (int.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int ToInt32(object value)
        {
            return ToInt32(value, 0);
        }
        #endregion

        #region ToInt64
        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static long ToInt64(object value, long defaultValue)
        {
            if (value != null)
            {
                long temp;
                if (long.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static long ToInt64(object value)
        {
            return ToInt64(value, 0);
        }
        #endregion

        #region ToUInt16
        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static ushort ToUInt16(object value, ushort defaultValue)
        {
            if (value != null)
            {
                ushort temp;
                if (ushort.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static ushort ToUInt16(object value)
        {
            return ToUInt16(value, default);
        }
        #endregion

        #region ToUInt32
        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static uint ToUInt32(object value, uint defaultValue)
        {
            if (value != null)
            {
                uint temp;
                if (uint.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static uint ToUInt32(object value)
        {
            return ToUInt32(value, default);
        }
        #endregion

        #region ToUInt64
        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static ulong ToUInt64(object value, ulong defaultValue)
        {
            if (value != null)
            {
                ulong temp;
                if (ulong.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static ulong ToUInt64(object value)
        {
            return ToUInt64(value, default);
        }
        #endregion

        #region ToFloat
        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static float ToFloat(object value, float defaultValue)
        {
            if (value != null)
            {
                float temp;
                if (float.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float ToFloat(object value)
        {
            return ToFloat(value, default);
        }
        #endregion

        #region ToDecimal
        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static decimal ToDecimal(object value, decimal defaultValue)
        {
            if (value != null)
            {
                decimal temp;
                if (decimal.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static decimal ToDecimal(object value)
        {
            return ToDecimal(value, default);
        }
        #endregion

        #region ToDouble
        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static double ToDouble(object value, double defaultValue)
        {
            if (value != null)
            {
                double temp;
                if (double.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }
        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static double ToDouble(object value)
        {
            return ToDouble(value, default);
        }
        #endregion

        #region ToLong
        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static long ToLong(object value, long defaultValue)
        {
            if (value != null)
            {
                long temp;
                if (long.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static long ToLong(object value)
        {
            return ToLong(value, default);
        }
        #endregion

        #region ToULong
        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static ulong ToULong(object value, ulong defaultValue)
        {
            if (value != null)
            {
                ulong temp;
                if (ulong.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static ulong ToULong(object value)
        {
            return ToULong(value, default);
        }
        #endregion

        #region ToShort
        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static short ToShort(object value, short defaultValue)
        {
            if (value != null)
            {
                short temp;
                if (short.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static short ToShort(object value)
        {
            return ToShort(value, default);
        }
        #endregion

        #region ToUShort
        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static ushort ToUShort(object value, ushort defaultValue)
        {
            if (value != null)
            {
                ushort temp;
                if (ushort.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static ushort ToUShort(object value)
        {
            return ToUShort(value, default);
        }
        #endregion

        #region ToByte
        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static byte ToByte(object value, byte defaultValue)
        {
            if (value != null)
            {
                byte temp;
                if (byte.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        public static byte? ToByte(object value, byte? defaultValue)
        {
            if (value != null)
            {
                byte temp;
                if (byte.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static byte ToByte(object value)
        {
            return ToByte(value, default);
        }

        #endregion

        #region ToSByte
        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static sbyte ToSByte(object value, sbyte defaultValue)
        {
            if (value != null)
            {
                sbyte temp;
                if (sbyte.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static sbyte ToSByte(object value)
        {
            return ToSByte(value, default);
        }
        #endregion

        #region ToSingle
        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static float ToSingle(object value, float defaultValue)
        {
            if (value != null)
            {
                float temp;
                if (float.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float ToSingle(object value)
        {
            return ToSingle(value, default);
        }
        #endregion

        #region ToDateTime
        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(object value, DateTime defaultValue)
        {
            if (value != null)
            {
                DateTime temp;
                if (DateTime.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        public static DateTime? ToDateTime(object value, DateTime? defaultValue)
        {
            if (value != null)
            {
                DateTime temp;
                if (DateTime.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(object value)
        {
            return ToDateTime(value, default);
        }
        #endregion

        #region ToChar
        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static char ToChar(object value, char defaultValue)
        {
            if (value != null)
            {
                char temp;
                if (char.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static char ToChar(object value)
        {
            return ToChar(value, default);
        }
        #endregion

        #region ToBoolean
        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static bool ToBoolean(object value, bool defaultValue)
        {
            if (value != null)
            {
                bool temp;
                if (bool.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        public static bool? ToBoolean(object value, bool? defaultValue)
        {
            if (value != null)
            {
                bool temp;
                if (bool.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        public static Guid ToGuid(object value, Guid defaultValue)
        {
            if (value != null)
            {
                Guid temp;
                if (Guid.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        public static Guid? ToGuidEmp(object value, Guid? defaultValue)
        {
            if (value != null)
            {
                Guid temp;
                if (Guid.TryParse(value.ToString(), out temp))
                {
                    return temp;
                }
            }
            return defaultValue;
        }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool ToBoolean(object value)
        {
            return ToBoolean(value, default);
        }
        #endregion


        /// <summary>复制类对象属性值
        /// 
        /// </summary>
        /// <param name="sourceObj">源对象</param>
        /// <param name="targetObj">目标对象</param>
        /// <returns>复制是否成功</returns>
        public static bool CopyPropertiesValue(object sourceObj, object targetObj)
        {
            bool isOk = true;
            try
            {
                var sourceType = sourceObj.GetType();
                var targetType = targetObj.GetType();

                var targetProperties = targetType.GetProperties();
                foreach (var targetProperty in targetProperties)
                {
                    var sourceProperty = sourceType.GetProperty(targetProperty.Name);
                    if (sourceProperty != null)
                    {
                        targetProperty.SetValue(targetObj, sourceProperty.GetValue(sourceObj));
                    }
                }
            }
            catch (Exception ex)
            {
                isOk = false;
            }

            return isOk;
        }

        public static string ToString(decimal? value, string format = "")
        {
            var strValue = "0";
            try
            {
                if (value.HasValue)
                {
                    if (string.IsNullOrEmpty(format))
                    {
                        strValue = value.Value.ToString();
                    }
                    else
                    {
                        strValue = value.Value.ToString(format);
                    }
                }
            }
            catch (Exception ex)
            {

            }
            return strValue;
        }

        /// <summary>
        /// 实现数据的向上取整
        /// </summary>
        /// <param name="v">要进行处理的数据</param>
        /// <param name="x">保留的小数位数</param>
        /// <returns>向上取整后的结果</returns>
        public static decimal Ceiling(decimal v, int x)
        {
            var isNegative = false;
            //如果是负数
            if (v < 0)
            {
                isNegative = true;
                v = -v;
            }

            var IValue = 1;
            for (var i = 1; i <= x; i++)
            {
                IValue = IValue * 10;
            }

            var Int = Math.Ceiling(v * IValue);
            v = Int / IValue;

            if (isNegative)
            {
                v = -v;
            }

            return v;
        }
    }
}
